package com.szholly.data.general;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.DynaProperty;

import net.sf.ezmorph.bean.MorphDynaBean;

import com.szholly.utils.util.DateUtils;
import com.szholly.utils.util.StringUtils;
import com.szholly.data.common.util.ValueConvertUtils;

/**
 * 定义基于Map对象的查询条件
 */
public class QueryMap implements IQueryMap {

	private boolean addCaption = false;
	private String selectFields;
	private HashMap<String, Object> whereMap = new HashMap<String, Object>();
	private String groupByString;
	private HashMap<String, Object> orderMap = new HashMap<String, Object>();
	private String outWhereString = "";

	/**
	 * 处理外来条件语句
	 * @return
	 */
	public String getWhereString() {
		return outWhereString;
	}

	/**
	 * 处理外来条件语句
	 */
	public void setWhereString(String whereString) {
		this.outWhereString = whereString;
	}

	@Override
	public void setAddCaptionField(boolean value) {
		this.addCaption = value;
	}

	@Override
	public boolean getAddCaptionField() {
		return addCaption;
	}

	@Override
	public String getSelectFields() {
		return selectFields;
	}

	@Override
	public void setSelectFields(String selectFields) {
		this.selectFields = selectFields;
	}

	@Override
	public HashMap<String, Object> getWhereMap() {
		return whereMap;
	}

	@Override
	public void setWhereMap(HashMap<String, Object> whereMap) {
		this.whereMap = whereMap;
	}

	@Override
	public String getGroupByString() {
		return groupByString;
	}

	@Override
	public void setGroupByString(String groupByString) {
		this.groupByString = groupByString;
	}

	@Override
	public HashMap<String, Object> getOrderByMap() {
		return orderMap;
	}

	@Override
	public void setOrderByMap(HashMap<String, Object> orderMap) {
		this.orderMap = orderMap;
	}

	@Override
	public String getKey() {
		String hashCode = "";
		if (!StringUtils.IsNullOrEmpty(this.getSelectFields()))
			hashCode += this.getSelectFields();
		else
			hashCode += "*";

		if (whereMap == null) {
			hashCode += "_null";
		} else {
			hashCode = getWereKey(whereMap);
		}

		if (!StringUtils.IsNullOrEmpty(this.getGroupByString()))
			hashCode += "_" + this.getGroupByString();
		else
			hashCode += "_null";

		if (orderMap == null) {
			hashCode += "_null";
		} else {
			Set<String> keys = orderMap.keySet();
			for (String key : keys) {
				hashCode += "_" + key + "_" + orderMap.get(key).toString();
			}
		}

		hashCode += "_" + this.getAddCaptionField();
		return hashCode;
	}

	@SuppressWarnings("unchecked")
	private String getWereKey(HashMap<String, Object> wheremap) {
		Set<String> keys = wheremap.keySet();
		String hashCode = "";
		for (String key : keys) {
			String[] fields = key.split(":");
			String field = null;
			String option = null;
			if (fields.length == 2) {
				field = fields[0];
				option = fields[1];
			} else {
				field = key;
				option = "=";
			}
			
			// 如果是or操作符
			if (field.trim().toLowerCase().equals("or")) {
				Object value = wheremap.get(key);
				HashMap<String, Object> orWhereMap = null;
				if (value instanceof Map) {
					orWhereMap = (HashMap<String, Object>) value;
				}
				if (orWhereMap != null) {
					hashCode += "_or_" + getWereKey(orWhereMap);
				}
			} else if (field.trim().toLowerCase().equals("and")) {
				Object value = wheremap.get(key);
				HashMap<String, Object> orWhereMap = null;
				if (value instanceof Map) {
					orWhereMap = (HashMap<String, Object>) value;
				}
				if (orWhereMap != null) {
					hashCode += "_and_" + getWereKey(orWhereMap);
				}
			} else{
				hashCode += getWhereKey(wheremap, key, option);
			}
		}
		return hashCode;
	}

	private String getWhereKey(HashMap<String, Object> wheremap, String key, String option) {
		String hashCode = "";
		Object value = wheremap.get(key);
		if (option.equals("isnull")) {
			hashCode += "_" + key + "_";
		} else if (option.equals("isnnull")) {
			hashCode += "_" + key + "_";
		} else {
			if (value == null || value.equals("")) {
				return hashCode;
			}
			hashCode += "_" + key + "_" + value.toString();
		}
		return hashCode;
	}

	@Override
	public IQueryFilter toQueryFilter(ITable owerTable) {
		IQueryFilter updateFilter = new QueryFilter();
		List<GlobalParameter> glo = new ArrayList<GlobalParameter>();
		String whereString = "";

		// 查看是否为Oracle
		boolean isOracleWorksapce = false;
		if (owerTable.getWorkspace().getWorkspaceType() == WorkspaceType.Oracle) {
			isOracleWorksapce = true;
		}

		if (whereMap != null) {
			whereString = getWhere(owerTable, whereMap, glo, isOracleWorksapce,
					true);
		}
		
		if(!StringUtils.IsNullOrSpace(outWhereString)){
			if(StringUtils.IsNullOrSpace(whereString)){
				whereString = outWhereString;
			}else{
				whereString = "(" + whereString + ") and (" + outWhereString + ")";
			}
		}

		updateFilter.setWhereString(whereString);
		updateFilter.setWhereParameter(glo.toArray(new GlobalParameter[glo
				.size()]));
		updateFilter.setAddCaptionField(addCaption);
		updateFilter.setGroupByString(groupByString);

		String orderString = "";
		if (orderMap != null) {
			Set<String> keys = orderMap.keySet();
			for (String key : keys) {
				if (orderMap.get(key).toString().equals("1")) {
					orderString += key + " ASC ,";
				} else {
					orderString += key + " DESC ,";
				}
			}
		}
		if (orderString != "") {
			orderString = orderString.substring(0, orderString.length() - 1);
		}
		updateFilter.setOrderByString(orderString);
		updateFilter.setSelectFields(selectFields);
		return updateFilter;
	}

	@SuppressWarnings("unchecked")
	private String getWhere(ITable owerTable, HashMap<String, Object> wheremap,
			List<GlobalParameter> glo, boolean isOracleWorksapce, boolean isAnd) {
		String whereString = "";
		Set<String> keys = wheremap.keySet();
		for (String key : keys) {
			String[] fields = key.split(":");
			String field = null;
			String option = null;
			if (fields.length == 2) {
				field = fields[0];
				option = fields[1];
			} else {
				field = key;
				option = "=";
			}

			// 如果是or操作符
			if (field.trim().toLowerCase().equals("or")) {
				Object value = wheremap.get(key);
				HashMap<String, Object> orWhereMap = null;
				if (value instanceof Map) {
					orWhereMap = (HashMap<String, Object>) value;
				}else if(value instanceof MorphDynaBean){
					orWhereMap = new HashMap<String, Object>();
					MorphDynaBean morphBean=((MorphDynaBean) value);
					DynaClass dyanCls=morphBean.getDynaClass();
					DynaProperty[] property=dyanCls.getDynaProperties();
					for (DynaProperty dynaProperty : property) {
						String fieldKey=dynaProperty.getName();
						Object fieldValue=morphBean.get(fieldKey);
						orWhereMap.put(fieldKey, fieldValue);
					}
				}
				if (orWhereMap != null) {
					String orWhereString = getWhere(owerTable, orWhereMap, glo,
							isOracleWorksapce, false);
					if (!orWhereString.equals("")) {
						if (isAnd) {
							whereString += "(" + orWhereString + ") and ";
						} else {
							whereString += "(" + orWhereString + ") or ";
						}
					}
				}
			} else if (field.trim().toLowerCase().equals("and")) {
				Object value = wheremap.get(key);
				HashMap<String, Object> orWhereMap = null;
				if (value instanceof Map) {
					orWhereMap = (HashMap<String, Object>) value;
				}
				if (orWhereMap != null) {
					String orWhereString = getWhere(owerTable, orWhereMap, glo,
							isOracleWorksapce, true);
					if (!orWhereString.equals("")) {
						if (isAnd) {
							whereString += "(" + orWhereString + ") and ";
						} else {
							whereString += "(" + orWhereString + ") or ";
						}
					}
				}
			}
			else {
				String innerWhere = getInnerWhere(owerTable, wheremap, glo,
						isOracleWorksapce, key, field, option);
				if (!innerWhere.equals("")) {
					if (isAnd) {
						whereString += innerWhere + " and ";
					} else {
						whereString += innerWhere + " or ";
					}
				}
			}
		}

		if (whereString != "") {
			if (isAnd) {
				whereString = whereString
						.substring(0, whereString.length() - 4);
			} else {
				whereString = whereString
						.substring(0, whereString.length() - 3);
			}
		}
		return whereString;
	}

	private String getInnerWhere(ITable owerTable,
			HashMap<String, Object> wheremap, List<GlobalParameter> glo,
			boolean isOracleWorksapce, String key, String field, String option) {

		String whereString = "";
		Object value = wheremap.get(key);
		boolean isDateField = false;
		if (isOracleWorksapce) {
			// 处理数据类型，确保Oracle等数据库在日期等数据查询时不出错
			Field f = owerTable.getField(field);
			if (f != null
					&& (f.getDataType() == GlobalDataType.Date || f
							.getDataType() == GlobalDataType.DateTime)) {
				isDateField = true;
				value = ValueConvertUtils.ConvertValue(f.getDataType(), null,
						value);
			}
		}

		if (option.equals("=")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (value.equals("\"null\"")) {
				whereString = field + " is null";
			} else {
				if (isOracleWorksapce && isDateField) {
					String dataString = DateUtils
							.convertDateTimeToString((Date) value);
					whereString = field + " = to_date('" + dataString
							+ "','yyyy-mm-dd hh24:mi:ss')";
				} else {
					whereString = field + " = @" + field + "";
					glo.add(new GlobalParameter("@" + field, value));
				}
			}
		} else if (option.equals(">")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (isOracleWorksapce && isDateField) {
				String dataString = DateUtils
						.convertDateTimeToString((Date) value);
				whereString = field + " > to_date('" + dataString
						+ "','yyyy-mm-dd hh24:mi:ss')";
			} else {
				whereString = field + " > @" + field + "";
				glo.add(new GlobalParameter("@" + field, value));
			}
		} else if (option.equals("!=")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (isOracleWorksapce && isDateField) {
				String dataString = DateUtils
						.convertDateTimeToString((Date) value);
				whereString = field + " != to_date('" + dataString
						+ "','yyyy-mm-dd hh24:mi:ss')";
			} else {
				whereString = field + " != @" + field + "";
				glo.add(new GlobalParameter("@" + field, value));
			}
		} else if (option.equals(">=")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (isOracleWorksapce && isDateField) {
				String dataString = DateUtils
						.convertDateTimeToString((Date) value);
				whereString = field + " >= to_date('" + dataString
						+ "','yyyy-mm-dd hh24:mi:ss')";
			} else {
				whereString = field + " >= @" + field + "";
				glo.add(new GlobalParameter("@" + field, value));
			}
		} else if (option.equals("<")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (isOracleWorksapce && isDateField) {
				String dataString = DateUtils
						.convertDateTimeToString((Date) value);
				whereString = field + " < to_date('" + dataString
						+ "','yyyy-mm-dd hh24:mi:ss')";
			} else {
				whereString = field + " < @" + field + "";
				glo.add(new GlobalParameter("@" + field, value));
			}
		} else if (option.equals("<=")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			if (isOracleWorksapce && isDateField) {
				String dataString = DateUtils
						.convertDateTimeToString((Date) value);
				whereString = field + " <= to_date('" + dataString
						+ "','yyyy-mm-dd hh24:mi:ss')";
			} else {
				whereString = field + " <= @" + field + "";
				glo.add(new GlobalParameter("@" + field, value));
			}
		} else if (option.equals("in")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			whereString = field + " in (" + value.toString() + ")";
		} else if (option.equals("nin")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			whereString = field + " not in (" + value.toString() + ")";
		} else if (option.equals("isnull")) {
			whereString = field + " is null";
		} else if (option.equals("isnnull")) {
			whereString = field + " is not null";
		} else if (option.equals("like")) {
			if (value == null || value.equals("")) {
				return whereString;
			}
			whereString = field + " like '%" + value.toString() + "%'";
			
		} else if (option.equals("%like")) { 
			whereString = field + " like '%" + value.toString() + "'";
		} else if (option.equals("like%")) { 
			whereString = field + " like '" + value.toString() + "%'";
		} else  {
			throw new RuntimeException("不支持的操作符【" + option + "】！");
		}
		return whereString;
	}

	@Override
	public Object getWhereObject() {
		return getMapWhereObject(whereMap);
	}

	@SuppressWarnings("unchecked")
	public Object getMapWhereObject(HashMap<String, Object> wheremap) {
		if (wheremap == null) {
			return new Object();
		}
//		DBObject queryCondition = new BasicDBObject();
//		Set<String> keys = wheremap.keySet();
//		for (String key : keys) {
//			String[] fields = key.split(":");
//			String field = null;
//			String option = null;
//			if (fields.length == 2) {
//				field = fields[0];
//				option = fields[1];
//			} else {
//				field = key;
//				option = "=";
//			}
//			// 如果是or操作符
//			if (field.trim().toLowerCase().equals("or")) {
//				Object value = wheremap.get(key);
//				HashMap<String, Object> orWhereMap = null;
//				if (value instanceof Map) {
//					orWhereMap = (HashMap<String, Object>) value;
//				}
//				DBObject innerQueryCondition = getDbWhere(orWhereMap, key, field, option);
//				if (innerQueryCondition != null) {
//					queryCondition.put("$or", innerQueryCondition);
//				}
//			} else {
//				DBObject innerQueryCondition = getDbWhere(wheremap, key, field, option);
//				if (innerQueryCondition != null) {
//					queryCondition.putAll(innerQueryCondition);
//				}
//			}
//		}
		return null;
	}

	private Object getDbWhere(HashMap<String, Object> wheremap, String key,
			String field, String option) {
//		DBObject queryCondition = new BasicDBObject();
//		Object value = wheremap.get(key);
//		if (option.equals("=")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			if (value.equals("\"null\"")) {
//				queryCondition.put(field, null);
//			} else {
//				queryCondition.put(field, value);
//			}
//		} else if (option.equals(">")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBObject v = new BasicDBObject("$gt", value);
//			queryCondition.put(field, v);
//		} else if (option.equals("!=")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBObject v = new BasicDBObject("$ne", value);
//			queryCondition.put(field, v);
//		} else if (option.equals(">=")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBObject v = new BasicDBObject("$gte", value);
//			queryCondition.put(field, v);
//		} else if (option.equals("<")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBObject v = new BasicDBObject("$lt", value);
//			queryCondition.put(field, v);
//		} else if (option.equals("<=")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBObject v = new BasicDBObject("$lte", value);
//			queryCondition.put(field, v);
//		} else if (option.equals("in")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBList values = new BasicDBList();
//			String[] valueStrings = value.toString().split(",");
//			for (String item : valueStrings) {
//				String itemValue = item;
//				itemValue = itemValue.trim();
//				if (itemValue.startsWith("'") && itemValue.endsWith("'")) {
//					itemValue = itemValue.substring(1);
//					itemValue = itemValue.substring(0, itemValue.length() - 1);
//				}
//				values.add(itemValue);
//			}
//			queryCondition.put(field, new BasicDBObject("$in", values));
//		} else if (option.equals("nin")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			BasicDBList values = new BasicDBList();
//			String[] valueStrings = value.toString().split(",");
//			for (String item : valueStrings) {
//				String itemValue = item;
//				itemValue = itemValue.trim();
//				if (itemValue.startsWith("'") && itemValue.endsWith("'")) {
//					itemValue = itemValue.substring(1);
//					itemValue = itemValue.substring(0, itemValue.length() - 1);
//				}
//				values.add(itemValue);
//			}
//			queryCondition.put(field, new BasicDBObject("$nin", values));
//		} else if (option.equals("isnull")) {
//			queryCondition.put(field, null);
//		} else if (option.equals("isnnull")) {
//			BasicDBObject v = new BasicDBObject("$ne", null);
//			queryCondition.put(field, v);
//		} else if (option.equals("like")) {
//			if (value == null || value.equals("")) {
//				return null;
//			}
//			Pattern pattern = Pattern.compile("^.*" + value.toString() + ".*$",
//					Pattern.CASE_INSENSITIVE);
//			queryCondition.put(field, pattern);
//		} else {
//			throw new RuntimeException("不支持的操作符【" + option + "】！");
//		}
		return null;
	}

	@Override
	public Object getOrderByObject() {
//		DBObject queryCondition = new BasicDBObject();
//		if (orderMap == null) {
//			return queryCondition;
//		}
//		queryCondition.putAll(orderMap);
		return null;
	}
}